// Keywords: nonWF, non-Wright-Fisher, meiotic drive, segregation distortion, intragenomic conflict

function (i)driveBreakpoints(o<Genome>$ gen1, o<Genome>$ gen2)
{
	// start with default breakpoints generated by the chromosome
	breaks = sim.chromosome.drawBreakpoints();
	
	// if both genomes have the drive, or neither, then just return
	gen1has = gen1.containsMarkerMutation(m2, D_pos);
	gen2has = gen2.containsMarkerMutation(m2, D_pos);
	if (gen1has == gen2has)
		return breaks;
	
	// will the drive be inherited?  do we want it to be?
	polarity = sum(breaks <= D_pos) % 2;   // 0 for gen1, 1 for gen2
	polarityI = (gen1has ? 0 else 1);
	desiredPolarity = (runif(1) < D_prob) ? polarityI else !polarityI;
	
	// intervene to produce the outcome we want
	if (desiredPolarity != polarity)
		return c(0, breaks);
	return breaks;
}

initialize() {
	initializeSLiMModelType("nonWF");
	defineConstant("K", 500);        // carrying capacity
	defineConstant("D_pos", 20000);  // meiotic drive allele position
	defineConstant("D_prob", 0.8);   // meiotic drive probability
	
	initializeMutationType("m1", 0.5, "f", 0.0);   // neutral
	m1.convertToSubstitution = T;
	
	initializeMutationType("m2", 0.1, "f", -0.1);  // drive allele
	m2.color = "red";
	m2.convertToSubstitution = F;
	
	initializeGenomicElementType("g1", m1, 1.0);
	initializeGenomicElement(g1, 0, 99999);
	initializeMutationRate(1e-7);
	initializeRecombinationRate(1e-8);
}
reproduction() {
	m = subpop.sampleIndividuals(1);
	b1 = driveBreakpoints(individual.genome1, individual.genome2);
	b2 = driveBreakpoints(m.genome1, m.genome2);
	subpop.addRecombinant(individual.genome1, individual.genome2, b1, m.genome1, m.genome2, b2);
}
1 early() {
	sim.addSubpop("p1", 10);
}
early() {
	p1.fitnessScaling = K / p1.individualCount;
}
100 early() {
	target = sample(p1.genomes, 10);
	target.addNewDrawnMutation(m2, D_pos);
}
100:1000 late() {
	mut = sim.mutationsOfType(m2);
	if (size(mut) == 0) {
		catn(sim.cycle + ": LOST");
		sim.simulationFinished();
	} else if (sim.mutationFrequencies(NULL, mut) == 1.0) {
		catn(sim.cycle + ": FIXED");
		sim.simulationFinished();
	}
}
